<!-- uniapp canvas流畅度问题 后续采用render.js方式做 -->
<script setup lang="ts">
import { ref, onMounted } from 'vue'

const canvasSize = 300
const radius = 25
const padding = 30
const selectedPoints = ref([])
const points = ref([])
const currentTouch = ref(null) // 当前触摸点的坐标
let ctx = null

// 初始化九宫格点位
const initPoints = () => {
  const gap = (canvasSize - 2 * padding - 3 * 2 * radius) / 2
  points.value = []
  for (let row = 0; row < 3; row++) {
    for (let col = 0; col < 3; col++) {
      const x = padding + radius + col * (gap + 2 * radius)
      const y = padding + radius + row * (gap + 2 * radius)
      points.value.push({ x, y, selected: false })
    }
  }
}

// 绘制九宫格
const drawGrid = () => {
  ctx.clearRect(0, 0, canvasSize, canvasSize)
  points.value.forEach((point) => {
    ctx.beginPath()
    ctx.arc(point.x, point.y, radius, 0, 2 * Math.PI)
    ctx.setStrokeStyle(point.selected ? '#627eed' : '#ccc')
    ctx.setLineWidth(2)
    ctx.stroke()
    ctx.closePath()

    if (point.selected) {
      ctx.beginPath()
      ctx.arc(point.x, point.y, radius / 2, 0, 2 * Math.PI)
      ctx.setFillStyle('#627eed')
      ctx.fill()
      ctx.closePath()
    }
  })

  // 绘制连接线
  if (selectedPoints.value.length > 0) {
    ctx.beginPath()
    ctx.setStrokeStyle('#627eed')
    ctx.setLineWidth(3)
    selectedPoints.value.forEach((index, idx) => {
      const point = points.value[index]
      if (idx === 0) {
        ctx.moveTo(point.x, point.y)
      } else {
        ctx.lineTo(point.x, point.y)
      }
    })

    // 如果有当前触摸点，绘制到手指的动态线
    if (currentTouch.value) {
      const lastSelectedPoint = points.value[selectedPoints.value[selectedPoints.value.length - 1]]
      ctx.lineTo(currentTouch.value.x, currentTouch.value.y)
    }
    ctx.stroke()
    ctx.closePath()
  }
  ctx.draw()
}

// 检测触摸点是否在某个圆内
const detectPoint = (touchX, touchY) => {
  for (let i = 0; i < points.value.length; i++) {
    const point = points.value[i]
    const dx = touchX - point.x
    const dy = touchY - point.y
    if (!point.selected && Math.sqrt(dx * dx + dy * dy) <= radius) {
      point.selected = true
      selectedPoints.value.push(i)
      break
    }
  }
}

const onTouchStart = (e) => {
  const { x, y } = e.changedTouches[0]
  detectPoint(x, y)
  currentTouch.value = { x, y } // 设置初始触摸点
  drawGrid()
}

const onTouchMove = (e) => {
  const { x, y } = e.changedTouches[0]
  currentTouch.value = { x, y } // 更新触摸点位置

  detectPoint(x, y)
  drawGrid()
}

const onTouchEnd = () => {
  console.log('手势密码序列:', selectedPoints.value)
  // 清空当前触摸点
  currentTouch.value = null
  // 重置状态
  setTimeout(() => {
    points.value.forEach((point) => (point.selected = false))
    selectedPoints.value = []
    drawGrid()
  }, 1000)
}

onMounted(() => {
  ctx = uni.createCanvasContext('gestureCanvas')
  initPoints()
  drawGrid()
})
</script>

<template>
  <view>
    <canvas
      style="width: 300px; height: 300px"
      canvas-id="gestureCanvas"
      id="gestureCanvas"
      @touchstart="onTouchStart"
      @touchmove="onTouchMove"
      @touchend="onTouchEnd"
    ></canvas>
  </view>
</template>

<style scoped>
canvas {
  display: block;
  margin: 20px auto;
}
</style>
